import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
import { useRefValue } from '@gnlab/utils/env-react'
import { Button, Modal, Input, message } from 'antd'
import services from '@/services'
import type { ThirdApp } from '@/services/features/third-apps'
import { type AceEditor, initAceEditor, loadAce } from './ace-editor'
import './index.module.less'

export function EditApp(props: { editing: ThirdApp | true | null; onFinish: () => void }) {
  const { editing, onFinish } = props

  return <Modal
    open={editing !== null}
    title={editing === true ? '添加自建应用' : '编辑自建应用'}
    onCancel={onFinish}
    styleName="editing"
    destroyOnClose
    footer={null}
    width="800px"
  >
    {editing !== null ? (
      <EditContent item={editing === true ? undefined : editing} onFinish={onFinish} />
    ) : null}
  </Modal>
}

function EditContent(props: { item?: ThirdApp; onFinish: () => void }) {
  const { item, onFinish } = props

  const [data, setData] = useState(() => item ?? { name: '', url: '', html: '', icon: '' })

  const setName = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setData({ ...data, name: e.target.value.trim() })
    },
    [data],
  )
  const setUrl = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setData({ ...data, url: e.target.value.trim() })
    },
    [data],
  )
  const setHTML = useCallback(
    (e: React.ChangeEvent<HTMLTextAreaElement>) => {
      setData({ ...data, html: e.target.value })
    },
    [data],
  )
  const setIcon = useCallback(
    (icon: string) => {
      setData({ ...data, icon })
    },
    [data],
  )

  const fileRef = useRef<HTMLInputElement>(null)

  const chooseFile = useCallback(() => {
    if (fileRef.current) fileRef.current.click()
  }, [fileRef])
  const onChooseFile = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files![0]
      e.target.value = ''
      if (file) {
        const res = await services.utils.upload(file)
        if (res.success) setIcon(res.data)
        else void message.error(`图片上传失败！${res.error}`)
      }
    },
    [setIcon],
  )

  const [saving, setSaving] = useState(false)
  const save = useCallback(async () => {
    setSaving(true)
    const res = await services.features.thirdApps.addOrUpdate({
      id: item?.id,
      name: data.name,
      url: data.url,
      html: data.html,
      icon: data.icon,
    })
    setSaving(false)
    if (res === true) onFinish()
    else void message.warning(`应用保存失败：${res}`)
  }, [item, data, onFinish])

  const [aceInited, setAceInited] = useState(false)
  const editorRef = useRef<HTMLDivElement>(null)
  const dataRef = useRefValue(data)
  useEffect(() => {
    const wrap = editorRef.current
    if (!wrap) return
    let cancelled = false
    let editor: AceEditor | null = null
    void loadAce().then(() => {
      if (cancelled) return
      const inner = document.createElement('div')
      wrap.appendChild(inner)
      editor = initAceEditor(inner, dataRef.current.html)
      if (editor) {
        setAceInited(true)
        editor.on('change', () => {
          setData(data => ({ ...data, html: editor!.getValue() }))
        })
      }
    })
    return () => {
      cancelled = true
      if (editor) editor.destroy()
      wrap.innerHTML = ''
      setAceInited(false)
    }
  }, [])

  return <div>
    <main>
      <section>
        <label>
          <span styleName="required">*</span>应用 Icon：
        </label>
        <div
          styleName="icon"
          onClick={chooseFile}
          style={{ backgroundImage: data.icon ? `url("${data.icon}")` : undefined }}
        >
          {!data.icon ? (
            <PlusOutlined />
          ) : (
            <div styleName="refresh">
              <RedoOutlined />
            </div>
          )}
          <input ref={fileRef} type="file" accept=".jpg,.jpeg,.png" onChange={onChooseFile} />
        </div>
      </section>
      <section>
        <label>
          <span styleName="required">*</span>应用名称：
        </label>
        <Input value={data.name} onChange={setName} />
      </section>
      <section>
        <label>应用 URL：</label>
        <Input value={data.url} onChange={setUrl} />
      </section>
      <section styleName="html">
        <label>应用 HTML：</label>
        <div>
          {!aceInited ? <Input.TextArea value={data.html} onChange={setHTML} rows={5} /> : null}
          <div ref={editorRef} styleName="ace-editor-wrap"></div>
          <div styleName="tips">URL 和 HTML 仅需填写一项</div>
        </div>
      </section>
    </main>
    <footer>
      <Button onClick={onFinish}>取消</Button>
      <Button
        type="primary"
        onClick={save}
        disabled={!data.name || !data.icon || (!data.url && !data.html)}
        loading={saving}
      >
        保存
      </Button>
    </footer>
  </div>
}
